/*oOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoO*/
/*
Authors: Ram Ovadia 201374022 and Lior Fass 300069705
Project: HW Assignment 3 
Description: This is the header of the double linked list module used in the project.  
*/
/*oOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoO*/

#ifndef LIST_H
#define LIST_H

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

//macro. Input: A pointer to List. Output: the number of ListNodes in the List. 
#define List_count(A) ((A)->count)

//macro. Input: A pointer to List. Output: pointer to value in first ListNode in List. 
#define List_first(A) ((A)->first != NULL ? (A)->first->value : NULL)

//macro. Input: A pointer to List. Output: pointer to value in last ListNode in List. 
#define List_last(A) ((A)->last != NULL ? (A)->last->value : NULL)

//macro. traverses the list from first to last, and allowes for operations on each ListNode. 
#define LIST_FOREACH(LIST, FIRST_PTR, NEXT_PTR, CURR_PTR) ListNode *_node = NULL;\
	ListNode *CURR_PTR = NULL;\
	for(CURR_PTR = _node = LIST->FIRST_PTR; _node != NULL; CURR_PTR = _node = _node->NEXT_PTR)

//struct ListNode;

typedef struct ListNode {
	struct ListNode *next;
	struct ListNode *prev;
	void *value;
} ListNode; //struct for each node in a doubly-linked list. 

typedef struct List {
	int count;
	ListNode *first;
	ListNode *last;
} List; //struct for doubly-linked list of nodes of type ListNode. 
//Maintains count of nodes, and pointers to first and last nodes.

typedef void (*Print_value_func)(void *); 
typedef int (*Comp_value_func)(void *, void*);
typedef void (*Free_value_func)(void *);

/*
* Allocates memory for List struct.     
* 
* Input:
* -----
* None     
*
* Output:
* -----
* Return Value:
* Pointer to allocated memory for list, or NULL if allocation failed. 
*/
List *List_create();

/*
* Destorys list. deallocated memory of List struct and all ListNodes.      
* 
* Input:
* -----
* list - pointer to List to be destoryed.      
*
* Output:
* -----
* Return Value:
* 0 - successful
* 1 - invalid list argument.  
*/
int List_destroy(List *list, Free_value_func free_value_func);

/*
* Clears all values in all ListNodes of list. all ListNodes value will point to NULL.      
* 
* Input:
* -----
* list - pointer to List to be cleard.      
*
* Output:
* -----
* Return Value:
* 0 - successful
* 1 - invalid list argument.  
*/
int List_clear(List *list, Free_value_func free_value_func);

/*
* Creates a new ListNode, and adds value to the end of the List.      
* 
* Input:
* -----
* list - pointer to List to which we want to add a new node.
* value - pointer to value to be pointed to by the new node. 
*
* Output:
* -----
* Return Value:
* 0 - successful
* 1 - invalid list argument.  
*/
int List_push(List *list, void *value);

/*
* Returns value held by the last ListNode in the list, and removes that ListNode from the List.        
* 
* Input:
* -----
* list - pointer to List from which we want to pop a new node. 
*
* Output:
* -----
* Return Value:
* if successful returns a pointer to the value held by the last ListNode in the List, otherwise returns NULL. 
*/
void *List_pop(List *list);

/*
* removes given node from list. assumes node is in list.        
* 
* Input:
* -----
* list - pointer to List from which we want to remove node. 
* node - pointer to ListNode in list which we want to remove. 
*
* Output:
* -----
* Return Value:
* if successful returns a pointer to the value held by the removed ListNode in the List, otherwise returns NULL. 
*/
void *List_remove(List *list, ListNode *node);

/*
* rearranges items in the ListNodes of list into a single preallocated array.
* Array items are copies of the original items, and are not linked         
* 
* Input:
* -----
* list - pointer to List from which we want create array.
* element_Array - pointer to a preallocated memmory that can hold all the items held by the the ListNodes of list. 
* size_of_element - size in bytes of each item held ny ListNodes in list. must all be of the same size. 
*
* Output:
* -----
* Return Value:
* 0 - successful, element_array will hold all items in list.
* 1 - unsuccessful. 
*/
int List_to_array(List *list, void * element_array, int size_of_element);

void List_print(List *list, Print_value_func print_value_func);

void *List_find(List *list, Comp_value_func comp_value_func, void *element);

int List_insert_sort(List *list, Comp_value_func comp_value_func); 

#endif //LIST_H
